#include <stdio.h> 
#include <unistd.h>
#include <stdlib.h>

// 全局变量（未初始化） - 位于BSS段
int g_unval;
// 全局变量（已初始化） - 位于数据段
int g_val = 100;

int main(int argc, char *argv[], char *env[])
{
  // 字符串常量 - 位于代码段/只读数据段
  const char *str = "helloworld";
  
  // 打印各种内存区域的地址
  printf("代码区地址: %p\n", main);                    // 代码段
  printf("已初始化全局变量地址: %p\n", &g_val);        // 数据段
  printf("未初始化全局变量地址: %p\n", &g_unval);      // BSS段
  
  // 静态局部变量 - 位于数据段
  static int test = 10;
  
  // 动态分配内存 - 位于堆区
  char *heap_mem = (char*)malloc(10);
  char *heap_mem1 = (char*)malloc(10);
  char *heap_mem2 = (char*)malloc(10);
  char *heap_mem3 = (char*)malloc(10);
  
  // 打印堆区地址（分配的内存块）
  printf("堆区地址1: %p\n", heap_mem);     
  printf("堆区地址2: %p\n", heap_mem1);    
  printf("堆区地址3: %p\n", heap_mem2);    
  printf("堆区地址4: %p\n", heap_mem3);    
  
  // 打印静态变量地址
  printf("静态变量地址: %p\n", &test);                
  
  // 打印栈区地址（局部变量的地址）
  printf("栈区地址1: %p\n", &heap_mem);    // 指针变量本身的地址在栈上
  printf("栈区地址2: %p\n", &heap_mem1);   
  printf("栈区地址3: %p\n", &heap_mem2);   
  printf("栈区地址4: %p\n", &heap_mem3);   
  
  // 打印只读字符串常量地址
  printf("只读字符串常量地址: %p\n", str);             
  
  // 打印命令行参数地址
  printf("命令行参数个数: %d\n", argc);
  for(int i = 0; i < argc; i++)
  {
    printf("命令行参数[%d]地址: %p\n", i, argv[i]);
  } 
  
  // 打印环境变量地址
  for(int i = 0; env[i]; i++)
  {
    printf("环境变量[%d]地址: %p\n", i, env[i]);
  }
  
  // 释放动态分配的内存
  free(heap_mem);
  free(heap_mem1);
  free(heap_mem2);
  free(heap_mem3);
  
  return 0;
}

